(* Copyright (C) 2010 School of Software Engineering, 
 * University of Science and Technology of China.
 *
 * This code is released under a BSD-style license.
 * See the file LICENSE for details.
 *)

structure Table: TABLE =
struct

datatype align
  = Left
  | Center
  | Right

datatype t
  = T of {aligns: align list,
          lines: string list list,
          lens: int list ref}

fun new aligns = T {aligns = aligns, lines = [], lens = ref []}

fun insertLine (T {aligns, lines, lens}, x) =
    T {aligns = aligns,
       lines = x::lines,
       lens = lens}

fun rev (T {aligns, lines, lens}) =
    T {aligns = aligns,
       lines = List.rev lines, 
       lens = lens}

fun output (table as T {aligns, lines, lens = l}) =
    let val lens = ref []
        val rec loopColumn =
         fn (from, to) =>
            if from=to
            then List.rev (!lens)
            else let val current = ref 0
                     val rec loopRow =
                      fn [] => lens := (!current)::(!lens)
                       | x::xs => 
                         let val k = String.size (List.nth (x, from))
                             val _ = if k>(!current)
                                     then current := k
                                     else ()
                         in  loopRow xs
                         end
                     val _ = loopRow lines
                 in  loopColumn (from+1, to)
                 end
        val lens = loopColumn (0, List.length aligns)
        val _ = l := lens
        val size = List.length lens
        val rec spaces =
         fn 0 => ""
          | n => String.concat [" ", spaces (n-1)]
        val rec doit =
         fn [] => ()
          | x::xs =>
            let val rec loopColumn =
                 fn (from, to) =>
                    if from = to
                    then ()
                    else let val _ = print (List.nth (x, from))
                             val _ = print (spaces (List.nth (lens, from) -
                                            String.size (List.nth (x, from))))
                         in  loopColumn (from+1, to)
                         end
                val _ = loopColumn (0, size)
                val _ = print "\n"
            in  doit xs
            end
    in  doit (lines)
    end

fun lens (T {lens, ...}) = !lens

end
